package cn.bonoon.kernel.descriptors.impl;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import cn.bonoon.kernel.descriptors.ObjectDescriptor;
import cn.bonoon.kernel.descriptors.ObjectPropertyAccessor;
import cn.bonoon.kernel.support.models.AbstractAjaxNode;
import cn.bonoon.kernel.support.models.AbstractItem;
import cn.bonoon.kernel.support.models.AbstractNode;

public final class ObjectDescriptorImpl extends MappableClassDescriptor<ObjectPropertyAccessor> implements ObjectDescriptor{

	/**
	 * 无效字段，一般无效字段是用来做特殊处理的，不用来生成值的转换的
	 */
	private final List<String> invalidProperties;
	
	public ObjectDescriptorImpl(Class<?> objectClass){
		super(objectClass);
		this.invalidProperties = new ArrayList<String>(1);
		this.invalidProperties.add("id");
	}
	
	@Override
	protected boolean filted(Class<?> cls) {
		return AbstractAjaxNode.class.equals(cls) 
				|| AbstractNode.class.equals(cls) 
				|| AbstractItem.class.equals(cls) 
				|| super.filted(cls);
	}
	
	@Override
	public ObjectDescriptor initDescriptor() {
		super.initDescriptor();
		for(String ip : invalidProperties){
			ObjectPropertyAccessor pa = properties.get(ip);
			if(null != pa){
				((ObjectPropertyAccessorImpl)pa).invalid();
			}
		}
		if(AbstractAjaxNode.class.isAssignableFrom(clazz)){
			addProperty("size", AbstractAjaxNode.class);
//		}else if(AbstractNode.class.isAssignableFrom(clazz)){
//			addProperty("parent", clazz);
		}
		return this;
	}
	
	private void addProperty(String name, Class<?> cls){
		try {
			properties.put(name, parseProperty(cls.getDeclaredField(name)));
		} catch (Exception e) {
			//nothing to do
			e.printStackTrace();
		}
	}
	
	@Override
	protected ObjectPropertyAccessorImpl parseProperty(Field field) {
		return new ObjectPropertyAccessorImpl(this, field);
	}
	
	@Override
	public Method getMethod(String name, Class<?>... parameterTypes) throws Exception {
		//如果定义了父类，则需要在父类查找
		Class<?> cc = clazz;
		do{
			try{
				return cc.getDeclaredMethod(name, parameterTypes);
			}catch(Exception ex){
				cc = cc.getSuperclass();
			}
		}while(!Object.class.equals(cc));
		throw new NoSuchMethodException();
	}
	
	public Constructor<?> getConstructor(Class<?>... parameterTypes) throws Exception {
		return clazz.getConstructor(parameterTypes);
	}
}
